---
title: Hono on Cloudflare with SST
description: Create and deploy a Hono API on Cloudflare with SST.
---

We are going to build an API with Hono, add an R2 bucket for file uploads, and deploy it using Cloudflare with SST.

:::tip[View source]
You can [view the source](https://github.com/sst/sst/tree/dev/examples/cloudflare-hono) of this example in our repo.
:::

Before you get started, make sure to [Create your Cloudflare API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/).

---

## 1. Create a project

Let's start by creating our app.

```bash
mkdir my-hono-api && cd my-hono-api
npm init -y
```

---

#### Init SST

Now let's initialize SST in our app.

```bash
npx sst@latest init
npm install
```

Select the defaults and pick **Cloudflare**. This'll create a `sst.config.ts` file in your project root.

---

#### Set the Cloudflare API token

You can save your Cloudflare API token in a `.env` file or just set it directly.

```bash
export CLOUDFLARE_API_TOKEN=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa
export CLOUDFLARE_DEFAULT_ACCOUNT_ID=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa
```

---

## 2. Add a Worker

Let's add a Worker. Update your `sst.config.ts`.

```js title="sst.config.ts"
async run() {
  const hono = new sst.cloudflare.Worker("Hono", {
    url: true,
    handler: "index.ts",
  });

  return {
    api: hono.url,
  };
}
```

We are enabling the Worker URL, so we can use it as our API.

---

## 3. Add an R2 Bucket

Let's add an R2 bucket for file uploads. Update your `sst.config.ts`.

```ts title="sst.config.ts"
const bucket = new sst.cloudflare.Bucket("MyBucket");
```

Add this above the `Worker` component.

#### Link the bucket

Now, link the bucket to our Worker.

```ts title="sst.config.ts" {3}
const hono = new sst.cloudflare.Worker("Hono", {
  url: true,
  link: [bucket],
  handler: "index.ts",
});
```

---

## 4. Upload a file

We want the `/` route of our API to upload a file to the R2 bucket. Create an `index.ts` file and add the following.

```ts title="index.ts" {4-8}
const app = new Hono()
  .put("/*", async (c) => {
    const key = crypto.randomUUID();
    await Resource.MyBucket.put(key, c.req.raw.body, {
      httpMetadata: {
        contentType: c.req.header("content-type"),
      },
    });
    return c.text(`Object created with key: ${key}`);
  });

export default app;
```

:::tip
We are uploading to our R2 bucket with the SDK — `Resource.MyBucket.put()`
:::

Add the imports.

```ts title="index.ts"
import { Hono } from "hono";
import { Resource } from "sst";
```

And install the npm packages.

```bash
npm install hono
```

---

## 5. Download a file

We want to download the last uploaded file if you make a `GET` request to the API. Add this to your routes in `index.ts`.

```ts title="index.ts"
const app = new Hono()
  // ...
  .get("/", async (c) => {
    const first = await Resource.MyBucket.list().then(
      (res) =>
        res.objects.sort(
          (a, b) => a.uploaded.getTime() - b.uploaded.getTime(),
        )[0],
    );
    const result = await Resource.MyBucket.get(first.key);
    c.header("content-type", result.httpMetadata.contentType);
    return c.body(result.body);
  });
```

We are getting a list of the files in the files in the bucket with `Resource.MyBucket.list()` and we are getting a file for the given key with `Resource.MyBucket.get()`.

---

#### Start dev mode

Start your app in dev mode.

```bash
npx sst dev
```

This will give you the URL of your API.

```bash frame="none"
✓  Complete
   Hono: https://my-hono-api-jayair-honoscript.sst-15d.workers.dev
```

---

#### Test your app

Let's try uploading a file from your project root. Make sure to use your API URL.

```bash
curl -X PUT --upload-file package.json https://my-hono-api-jayair-honoscript.sst-15d.workers.dev
```

Now head over to `https://my-hono-api-jayair-honoscript.sst-15d.workers.dev` in your browser and it'll load the file you just uploaded.

---

## 6. Deploy your app

Finally, let's deploy your app!

```bash
npx sst deploy --stage production
```

You can use any stage name here but it's good to create a new stage for production.

